#ifndef MESH_HPP_
#define MESH_HPP_

#include <iostream>
#include <fstream>
#include <stddef.h>
#include <stdexcept>
#include "blinalg.hpp"
#include "usertypes.hpp"
#include "string.h"

#define MAX_MESH_LEVELS (15)

//-------------- FElement--------------------------
myindex readMeshFE(const char *fileName)
{
  std::ifstream txt_file;
  char txt_file_name[250];
  // open files
  strcpy_s (txt_file_name, fileName);
  strcat_s (txt_file_name, ".txt");
  txt_file.open(txt_file_name, std::ios::in);
  assert(txt_file.good ()); 
  // read mesh
  myindex nr;
  txt_file >> nr;
  txt_file.close();
  return nr;
}

void readMeshFE(const char *fileName, double a, double b)
{
  std::ifstream txt_file;
  char txt_file_name[250];
  // open files
  strcpy_s (txt_file_name, fileName);
  strcat_s (txt_file_name, ".txt");
  txt_file.open(txt_file_name, std::ios::in);
  assert(txt_file.good ()); 
  // read mesh
  myindex nr;
  txt_file >> nr >> a >> b;
  txt_file.close();
  return;
}

void khoiTaoLuoi(std::vector<FElement>& elem, const char *fileName)
{
  double vertex0_coord, vertex1_coord;
  myindex midpoint_index = 0, level=0, idx=0, vertex0_index = 0, vertex1_index = 1, father=0;
  myindex N;
  double a, b;

  std::ifstream txt_file;
  char txt_file_name[250];
  // open files
  strcpy_s (txt_file_name, fileName);
  strcat_s (txt_file_name, ".txt");
  txt_file.open(txt_file_name, std::ios::in);
  assert(txt_file.good ());
  // read mesh
  txt_file >> N >> a >> b;
  txt_file.close();
  vertex0_coord = a;
  vertex1_coord = b;
  elem = vector<FElement>(1);
  elem[0].fill (vertex0_coord, vertex1_coord, vertex0_index, vertex1_index, 
	midpoint_index, level, idx, father);
}

void lamMinLuoi(std::vector<FElement>& elem, myindex max_refine)
{
  if (max_refine >= MAX_MESH_LEVELS)
    throw std::out_of_range("Mesh::Refinement: no further refinement provided");
  /*double vertex0_coord, vertex1_coord;
  myindex level, idx, vertex0_index, vertex1_index, father, midpoint_index = 0;
  myindex N,i,k,index;
  N = readMeshFE("fem");
  for(i=0;i<max_refine;i++)
  {
    level = i+1;
    for(k=0;k<N;k++)
    {
      index = N-1-k;
      father = index;
      idx = 2*index+1;
      vertex0_coord = elem[index].getMidpoint();
      vertex1_coord = elem[index].getVertexCoord(1);
      vertex0_index = 2*N-k;
      vertex1_index = elem[index].getVertexIndex(1);
      elem[2*index+1].fill(vertex0_coord, vertex1_coord, vertex0_index, vertex1_index, 
	midpoint_index, level, idx, father);

      idx = 2*index;
      vertex0_coord = elem[index].getVertexCoord(0);
      vertex1_coord = elem[index].getMidpoint();
      vertex0_index = elem[index].getVertexIndex(0);
      vertex1_index = 2*N-k;
      elem[2*index].fill(vertex0_coord, vertex1_coord, vertex0_index, vertex1_index, 
	midpoint_index, level, idx, father);
    }
    N *= 2;
  }*/
	long n, k;
	n =  readMeshFE("fem");
	vector<FElement> v_tmp;
	for (int i = 1; i <= max_refine; i++)
	{
		n*=2;
		v_tmp = vector<FElement>(n);
		k = 0;
		for (int j = 0; j < elem.size(); j++)
		{
			v_tmp[k].fill(elem[j].getVertexCoord(0), elem[j].getMidpoint(), k, k+1, 0, 0, 0, 0);
			k++;
			v_tmp[k].fill(elem[j].getMidpoint(), elem[j].getVertexCoord(1), k, k+1, 0, 0, 0, 0);
			k++;
		}
		elem = v_tmp;
	}
}

#endif // MESH_HPP_
